﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonLib;
using ElementLib.Interface;
using HalconDotNet;
using System.Windows.Forms;
namespace ElementLib
{
    public class LL : IComplexMes
    {

        private int type;
        private List<LinePack> linePacks;
        public delegate void drawFunc(string type);
        private Output output;
        private string name;
        private static int[] existCount = new int[10];
        private List<string> nameList;
        private double supOffsetRow, supOffsetColumn;
        private SupportLine supportLine;


        public double SupOffsetRow
        {
            get { return supOffsetRow; }
            set { supOffsetRow = value; }
        }

        public double SupOffsetColumn
        {
            get { return supOffsetColumn; }
            set { supOffsetColumn = value; }
        }

        public SupportLine SupportLine
        {
            get { return supportLine; }
            set { if (supportLine != null) supportLine.Dispose(); supportLine =  value; }
        }

        public LL()
        {
            nameList = new List<string>();
            linePacks = new List<LinePack>();
        }


        public List<string> NameList
        {
            get { return nameList; }
            set
            {

                foreach (var item in value)
                {
                    nameList.Add(item);
                }
            }
        }
        public LL(LL ll)
        {
            supOffsetRow = ll.supOffsetRow;
            supOffsetColumn = ll.supOffsetColumn;
            name = ll.name;
            nameList = new List<string>();
            foreach (var item in ll.nameList)
            {
                nameList.Add(item);
            }
            type = ll.type;
            output = new Output(ll.output);
            linePacks = new List<LinePack>();
            foreach (var item in ll.linePacks)
            {
                linePacks.Add(new LinePack(item));
            }
        }

        public void ApplyChange(string mode)
        {


            switch (type)
            {
                case ConstValue.MEASURE_LL_Concate:
                    if (mode == "add") name = "llConcat" + existCount[0]++;
                    break;
                case ConstValue.MEASURE_LL_Cross:
                    if (mode == "add") name = "llCross" + existCount[1]++;
                    break;
                case ConstValue.MEASURE_LL_Dist:
                    if (mode == "add") name = "llDist" + existCount[2]++;
                    if (supportLine != null)
                    {
                        supOffsetRow = supportLine.RowOffset;
                        supOffsetColumn = supportLine.ColumnOffset;
                    }

                    break;
                case ConstValue.MEASURE_LL_InnerC:
                    if (mode == "add") name = "llInnerC" + existCount[3]++;
                    break;
                case ConstValue.MEASURE_LL_Mid:
                    if (mode == "add") name = "llMid" + existCount[4]++;

                    break;
                default:
                    break;
            }
        }
        public Output Rs
        {
            set { output = value; }
            get { return output; }
        }

        public List<LinePack> LinePacks
        {
            get { return linePacks; }
            set { linePacks = value; }
        }
        public string Name { get { return name; } set { name = value; } }

        public int Type { get { return type; } set { type = value; } }
        public bool loadElem(List<IElemPack> ieps)
        {
            linePacks = new List<LinePack>();
            if (ieps.Count == 0)
            {
                MessageBox.Show("至少选择两条边");
                return false;
            }
            for (int i = 0; i < ieps.Count; i++)
            {
                string name = ieps[i].GetType().FullName;
                if (name != ConstValue.TYPE_LINEPACK)
                {
                    MessageBox.Show("混有其他基本元素");
                    return false;
                }
                linePacks.Add(new LinePack((LinePack)ieps[i]));
            }
            ieps.Clear();
            return true;
        }

        public void CompleteChildElem()
        {

        }

        /// <summary>
        /// 实际测量的时候用这个
        /// </summary>
        /// <param name="image"></param>
        /// <param name="homMat2D"></param>
        /// <param name="angle"></param>
        /// <param name="add"></param>
        /// <param name="find"></param>
        /// <param name="addSupline"></param>
        public void Execute(HObject image, HTuple homMat2D, HTuple angle, AddToList add, FindMethod find, AddSupline addSupline)
        {

            for (int i = 0; i < linePacks.Count; i++)
            {
                if (linePacks[i].IsDetectType())
                {
                    var linePtr = linePacks[i].Detect(image, homMat2D);
                    if (linePtr == null) { MessageBox.Show("没有检测到"); throw new Exception(); }
                    else
                    {
                        linePacks[i].L = new Line(linePtr);
                        add(linePacks[i], ConstValue.LINE);
                    }
                }
                else
                {
                    var linePtr = find(linePacks[i].Name, ConstValue.LINE);
                    if (linePtr == null)
                    {
                        MessageBox.Show("没有检测到"); throw new Exception();
                    }
                    else
                    {
                        linePacks[i].L = new Line((Line)linePtr);
                        add(linePacks[i], ConstValue.LINE);
                    }
                }

            }

            if (linePacks.Count < 2) throw new Exception();
            Output output = null;
            HTuple row, column, rowBegin, rowEnd, colBegin, colEnd, radius;
            HObject contourTuple = null, concatLine = null, ho_Circle = null, midLineContours = null;
            List<Point> tempPoints = new List<Point>();
            Line rsLine= null;
            switch (type)
            {
                case ConstValue.MEASURE_LL_Concate:

                    foreach (var linePack in linePacks)
                    {
                        if (contourTuple == null)
                        {
                            contourTuple = new HObject(linePack.Contours());
                        }
                        else
                        {
                            contourTuple = contourTuple.ConcatObj(linePack.Contours());
                        }
                    }

                    GeoMethod.LL_Concate(contourTuple, out concatLine, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    rsLine = new Line(new Point(rowBegin, colBegin), new Point(rowEnd, colEnd), "连接线" + existCount[0]++);
                    add(new LinePack() { L = rsLine, Name = rsLine.Name }, ConstValue.LINE);
                    //output = new Output(rsLine, ConstValue.LINE);
                    break;
                case ConstValue.MEASURE_LL_Cross:
                    GeoMethod.LL_Cross(linePacks[0].Contours(), linePacks[1].Contours(), out row, out column);
                    Point point = new Point(row, column);
                    PointPack pointPack = new PointPack(){  P = point, Name = point.Name  };
                    //output = new Output(point, ConstValue.POINT);
                    break;
                case ConstValue.MEASURE_LL_Dist:
                    HTuple distance;
                    supOffsetRow = supportLine.RowOffset;
                    supOffsetColumn = supportLine.ColumnOffset;
                    supportLine.SetOffset(supOffsetRow, supOffsetColumn);
                    GeoMethod.LL_Dist(linePacks[0].Contours(), linePacks[1].Contours(), out distance);
                    //output = new Output((double)distance, ConstValue.DISTANCE);
                    break;
                case ConstValue.MEASURE_LL_InnerC:

                    foreach (var line in linePacks)
                    {

                        if (contourTuple == null)
                        {
                            contourTuple = new HObject(line.Contours());
                        }
                        else
                        {
                            contourTuple = contourTuple.ConcatObj(line.Contours());
                        }
                    }

                    GeoMethod.LL_InnerC(contourTuple, out ho_Circle, out row, out column, out radius);
                    Circle rsCircle = new Circle(new Point(row, column), radius, ho_Circle);
                    CirclePack circlePack = new CirclePack() { Name = rsCircle.Name, C = rsCircle };
                    add(circlePack, ConstValue.CIRCLE);
                    output = new Output(rsCircle, ConstValue.CIRCLE);
                    break;
                case ConstValue.MEASURE_LL_Mid:

                    GeoMethod.LL_Mid(linePacks[0].Contours(), linePacks[1].Contours(), out midLineContours, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    rsLine = new Line(new Point(rowBegin, colBegin), new Point(rowEnd, colEnd),"平分线" + existCount[4]++);
                    add(new LinePack() { L=rsLine,Name=rsLine.Name}, ConstValue.LINE);
                    //output = new Output(rsLine,ConstValue.LINE);
                    break;
                default:
                    break;
            }
       
        }
        /// <summary>
        /// 规划测量的时候用这个
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public Output Execute(FindMethod method)
        {
            if (nameList != null)
            {
                foreach (var name in nameList)
                {
                    Line line = (Line)method(name, ConstValue.LINE);
                    if (line == null)
                    {
                        throw new Exception();
                    }
                    linePacks.Add(new LinePack() { L = new Line(line) });
                }
            }
            if (linePacks.Count < 2) throw new Exception();
            HTuple row, column, rowBegin, rowEnd, colBegin, colEnd,radius;
            HObject contourTuple = null,concatLine = null,ho_Circle = null, midLineContours = null;
            List<Point> tempPoints = new List<Point>();
            switch (type)
            {
                case ConstValue.MEASURE_LL_Concate:
                  
                    foreach (var linePack in linePacks)
                    {
                        if (contourTuple == null)
                        {
                            contourTuple = new HObject(linePack.Contours());
                        }
                        else
                        {
                            contourTuple = contourTuple.ConcatObj(linePack.Contours());
                        }
                    }

                    GeoMethod.LL_Concate(contourTuple, out concatLine, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    output = new Output(new Line(new Point(rowBegin, colBegin), new Point(rowEnd, colEnd)), ConstValue.LINE);
                    break;
                case ConstValue.MEASURE_LL_Cross:
                    GeoMethod.LL_Cross(linePacks[0].Contours(), linePacks[1].Contours(), out row, out column);
                    output = new Output(new Point(row, column), ConstValue.POINT);
                    break;
                case ConstValue.MEASURE_LL_Dist:
                    HTuple distance;
                   
                    GeoMethod.LL_Dist(linePacks[0].Contours(), linePacks[1].Contours(), out distance);
                    supportLine = new SupportLine(LinePacks[0].L.midPoint(), LinePacks[1].L.midPoint());
                    output = new Output((double)distance, ConstValue.DISTANCE);
                    break;
                case ConstValue.MEASURE_LL_InnerC:
          
                    foreach (var line in linePacks)
                    {
                      
                        if (contourTuple == null)
                        {
                            contourTuple = new HObject(line.Contours());
                        }
                        else
                        {
                            contourTuple = contourTuple.ConcatObj(line.Contours());
                        }
                    }

                    GeoMethod.LL_InnerC(contourTuple, out ho_Circle, out row, out column, out radius);
                    output = new Output(new Circle(new Point(row, column), radius, ho_Circle), ConstValue.CIRCLE);
                    break;
                case ConstValue.MEASURE_LL_Mid:
                 
                    GeoMethod.LL_Mid(linePacks[0].Contours(), linePacks[1].Contours(), out midLineContours, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    output = new Output(new Line(new Point(rowBegin, colBegin), new Point(rowEnd, colEnd), "平分线" + existCount[4]++), ConstValue.LINE);
                    break;
                default:
                    break;
            }
            return output;
        }

        public void Unload()
        {
            for (int i = 0; i < linePacks.Count; i++)
            {
                linePacks[i].Unload();
            }
        }
        public void Dispose()
        {
            foreach (var item in linePacks)
            {
                item.Dispose();
            }
            linePacks.Clear();
        }
        
    }
}
